/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

 #include "AppTask.h"
 #include "esp_log.h"
 #include "cJSON.h"
 #include <app_uart.h>
 #include <sstream>
 #include "app_mqtt_util.h"
 #include "app_uart_util.h"
 #include "app_ota.h"
 
 #include "Button.h"
 #include "LEDWidget.h"
 
 #include <system/SystemClock.h>
 #include <platform/CHIPDeviceLayer.h>
 #include <app/server/Server.h>
 #include <app/clusters/door-lock-server/door-lock-server.h>
 
 #include "lockly_c_header.h"
 #include "uart_util.h"
 #include "driver/gpio.h"
 
 #include <esp_matter.h>
 #include <esp_matter_core.h>
 #include <esp_matter_bridge.h>
 
 #include <app_bridged_device.h>
 #include "rf_sensor.h"
 #include "app_ecdh.h"
 #include "esp_heap_caps.h"
 #include <time.h>
 #include "lock_event_def.h"
 #include "app_pair.h"
 
 /* BLE */
 #include "esp_central.h"
 
 #define APP_TASK_NAME "Matter_Bridge"
 
 
 #define BLEScanTimeout_MS 30000
 
 
 #define SYSTEM_STATE_LED GPIO_NUM_18
 #define SYSTEM_STATE_LED_GREEN GPIO_NUM_19
 
 #define APP_FUNCTION_BUTTON GPIO_NUM_26
 #define APP_BUTTON_DEBOUNCE_PERIOD_MS 50
 
 #define FACTORY_RESET_TRIGGER_TIMEOUT 2000
 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 1000
 #define FACTORY_RESET_BUTTON_AVAIABLE_WINDOW 15000 //Change to 20 seconds for factory reset button available window
 
 #define SERVER_INIT_WINDOW 300000
 
 
 #define APP_EVENT_QUEUE_SIZE 20
 #define APP_TASK_STACK_SIZE (6656)
 #define APP_TASK_PRIORITY 4
 
 #define LOCK_STATUS_BIT 1
 #define HAS_WIRED_DS_BIT 2
 #define WIRED_DS_STATUS_BIT 4
 #define HAS_RF_DS_BIT 8
 #define HAS_RF_STATUS_BIT 16
 #define SECURE_MODE_BIT 32
 #define SECURE_LOCK_BIT 64
 #define LOW_BAT_BIT 128
 
 static const char * const TAG = "App-Task";
 
 static const char * const GATTC_TAG = "GATT-TAG";
 
 extern "C" {
     void ble_scan_status_debug(void);
     void read_freq_chal(void);	
     void Set_Frequece_Init(void);	
     uint8_t get_current_chal(void);
 }
 
 
 namespace {
 
 TimerHandle_t sScanDevTimer;
 TimerHandle_t sRestartTimer;
 TimerHandle_t sInitWatchdogTimer;
 
 
 
 BaseType_t sAppTaskHandle;
 QueueHandle_t sAppEventQueue;
 
 
 StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)];
 } // namespace
 
 using namespace ::chip::DeviceLayer;
 using namespace ::chip::System;
 using namespace ::chip::System::Clock;
 using namespace ::chip::app::Clusters::DoorLock;
 using namespace esp_matter;
 
 
 AppTask AppTask::sAppTask;
 static uint32_t alloc_failed_count=0;
 bool isIdentifying = 0;
 static bool startedWifiProvioning = 0;
 
 uint32_t get_alloc_failed_count(void)
 {
     return alloc_failed_count;
 }
 
 esp_err_t AppTask::StartAppTask()
 {
     sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent));
     if (sAppEventQueue == NULL)
     {
         ESP_LOGE(TAG, "Failed to allocate app event queue"); 
         return ESP_FAIL;
     }
 
     // Start App task.
     sAppTaskHandle = xTaskCreate(AppTaskMain, APP_TASK_NAME, ArraySize(appStack), NULL, APP_TASK_PRIORITY, NULL);
     return sAppTaskHandle ? ESP_OK : ESP_FAIL;
 }
 
 void SetHubId(void)
 {
     if(!ConnectivityMgr().IsWiFiStationProvisioned()){
         ESP_LOGI(TAG, "SetBLEDeviceName");
         //Note: kMaxDeviceNameLength should be changed to 32
         ConnectivityMgr().SetBLEDeviceName(get_hub_id());						
         ConnectivityMgr().SetBLEAdvertisingEnabled(true);			
         ConnectivityMgr().SetBLEAdvertisingMode(ConnectivityMgr().kFastAdvertising);
     }			
 }
 
 void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name)
 {
     alloc_failed_count++;
     printf("%s was called but failed to allocate %d bytes with 0x%" PRIX32 " capabilities. \n",function_name, requested_size, caps);
     ESP_LOGE(TAG, "free heap size is %" PRIu32 ", minimum %" PRIu32, esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
     if(is_mqtt_connected&&alloc_failed_count>5){
        ESP_LOGE(TAG, "Memory is too low, restarting...");
        GetAppTask().AppScheduleWork(restartAfterProvisioning, NULL); 
     }
 }
 
 esp_err_t AppTask::Init()
 {
     esp_err_t err = ESP_OK;
     // Create FreeRTOS sw timer for Function Selection
 
     sScanDevTimer = xTimerCreate("ScanDevTmr",          // Just a text name, not used by the RTOS kernel
                                   10000/portTICK_PERIOD_MS,                // == default timer period (mS)
                                   true,            // timer reload (==one-shot)
                                   (void *) this,    // init timer id = app task obj context
                                   ScanDevTimerEventHandler // timer callback handler
     );
     sRestartTimer = xTimerCreate(
                                 "RestartTimer",             // Just a text name, not used by the RTOS kernel
                                 pdMS_TO_TICKS(1800000),     // Set timer period to 3 minutes
                                 //aTimeoutInMs,     // Set timer period to 2 minutes
                                 false,                    // Auto start
                                 (void *)0,                  // The id is not used, so can be set to anything
                                 RestartTimerEventHandler        // The callback function that inspects the status of all the other tasks
     );
     sInitWatchdogTimer = xTimerCreate(
                                 "InitWatchdogTimer",             // Just a text name, not used by the RTOS kernel
                                 pdMS_TO_TICKS(300000),     // Set timer period to 5 minutes
                                 false,                    // The timer will not auto-reload itself when it expires
                                 (void *)0,                  // The id is not used, so can be set to anything
                                 InitWatchdogEventHandler        // The callback function that inspects the status of all the other tasks
     );
 
 
     ble_diagnose_init();
     ESP_LOGI(TAG, "Activated ble diagnose!!!");
     err = hub_info_init();
     InitialiseHubAttributes();
     if(err!=ESP_OK){		
         ESP_LOGI(TAG, "Didn't Flash MFG Data");
     }
     DeviceLayer::PlatformMgr().ScheduleWork(SetHubId, NULL); 
     heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
     return err;
 }
 
 
 
 void printTaskInfo()
 {
     // Allocate a buffer to store task details
     TaskStatus_t *taskArray;
     volatile UBaseType_t taskCount;
     uint32_t totalRunTime;
 
     // Get the number of tasks
     taskCount = uxTaskGetNumberOfTasks();
 
     // Allocate a TaskStatus_t structure for each task
     taskArray = (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t));
 
     if (taskArray != NULL)
     {
         // Get the task status information
         taskCount = uxTaskGetSystemState(taskArray, taskCount, &totalRunTime);
 
         // Print each task's information
         for (UBaseType_t i = 0; i < taskCount; i++)
         {
             // ESP_LOGI("Task Info", "Task: %s, Stack High Water Mark: %u"//, Runtime: %d",
             //          taskArray[i].pcTaskName, 
             //          taskArray[i].usStackHighWaterMark, 
             //          taskArray[i].ulRunTimeCounter);
             printf("Task: %s, Stack High Water Mark: %" PRIu32 ", Runtime: %" PRIu32 "\n",
                    taskArray[i].pcTaskName, 
                    taskArray[i].usStackHighWaterMark, 
                    taskArray[i].ulRunTimeCounter);
 
         }
 
         // Free the allocated memory
         vPortFree(taskArray);
     }
 }
 
 void printHeapInfo()
 {
     char buffer[256];
     sprintf(buffer, "\t /     Free /    Total\n"
                     " SRAM : [/ %8d / %8d]\n"
                     "PSRAM : [/ %8d / %8d]\n",
             // heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL),
             heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
             heap_caps_get_total_size(MALLOC_CAP_INTERNAL),
             // heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM),
             heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
             heap_caps_get_total_size(MALLOC_CAP_SPIRAM));
     printf("------------ Memory ------------\n");
     printf("%s", buffer);
     printf("low watermarks of SRAM : %d \r\n", heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL));
     printf("low watermarks of PSRAM : %d \r\n", heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));
     printf(".esp_get_free_heap_size = %ld\n\r", esp_get_free_heap_size());
 }
 
 void AppTask::AppTaskMain(void * pvParameter)
 {
     AppEvent event;
     Clock::Timestamp lastChangeTime = Clock::kZero;
     esp_err_t err = sAppTask.Init();
     if (err != ESP_OK)
     {
         ESP_LOGI(TAG, "AppTask.Init() failed");
         return;
     }
     ESP_LOGI(TAG, "App Task started");
     if(ConnectivityMgr().IsWiFiStationProvisioned()){
         ESP_LOGE(TAG, "WiFi is provisioned");
         closeMatterCommissioningWindows();  // 已经配过网了
         startedWifiProvioning = false;
         if(sInitWatchdogTimer)
             xTimerStart(sInitWatchdogTimer, 0); //Start watchdog timer to check if the mqtt can be connected in 5 minutes
 
     }else{
         ESP_LOGE(TAG, "WiFi is NOT provisioned");		
         startedWifiProvioning = true;
     }	
 
     while (true)
     {
         BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, 10/portTICK_PERIOD_MS);
         while (eventReceived == pdTRUE)
         {
             sAppTask.DispatchEvent(&event);
             eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
             vTaskDelay(pdMS_TO_TICKS(10)); // 让出 CPU, 给看门狗重置的机会
         }
 
         if (chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen())
         {
             static bool bleConnectFlag = 0;
             GetAppTask().PostBlePairForWifiConnect();
             // if(ConnectivityMgr().IsWiFiStationConnected())
             if (PlatformMgr().TryLockChipStack())
             {
                 // ble 连接后
                 if (ConnectivityMgr().NumBLEConnections())
                 {
                     bleConnectFlag = true;
                 }
                 // ble 连接又断开后，表示配网事件结束，关闭配网窗口
                 if (bleConnectFlag)
                 {
                     if (!ConnectivityMgr().NumBLEConnections())
                     {
                         closeMatterCommissioningWindows();
                         bleConnectFlag = false;
                     }
                 }
                 PlatformMgr().UnlockChipStack();
             }
         }
 
         Clock::Timestamp now			= SystemClock().GetMonotonicTimestamp();
         Clock::Timestamp nextChangeTime = lastChangeTime + Clock::Seconds16(5);
     
         if (nextChangeTime < now)
         {
             lastChangeTime = now;			
             uint64_t timestamp = get_timestamp_ms();
             if(ConnectivityMgr().IsWiFiStationProvisioned()){
                 GetAppTask().MonitorOnlinestatus();		
                 CheckRFsensorTimeout();
             }
             ESP_LOGE(TAG, "free sram heap size is %d , minimum %d", heap_caps_get_free_size(MALLOC_CAP_INTERNAL),heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL));
             ESP_LOGE(TAG, "free psram heap size is %d , minimum %d", heap_caps_get_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM));            
             // printHeapInfo();
         }
         CheckRFsensorState();
     }
 }
 
 /*
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
 static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
 {
     uint8_t *adv_name = NULL;
     uint8_t adv_name_len = 0;
     switch (event) {
     case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
         //the unit of the duration is second
         uint32_t duration = BLEScanTimeout_MS/1000;
         esp_ble_gap_start_scanning(duration);
         break;
     }
     case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
         //scan start complete event to indicate scan start successfully or failed
         if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
             ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status);
             break;
         }
         ESP_LOGI(GATTC_TAG, "scan start success");
 
         break;
     case ESP_GAP_BLE_SCAN_RESULT_EVT: {
         esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
         switch (scan_result->scan_rst.search_evt) {
         case ESP_GAP_SEARCH_INQ_RES_EVT:
           //  esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
           //  ESP_LOGI(GATTC_TAG, "searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
             adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,
                                                 ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
 
             if (adv_name != NULL) {
                 
                 uint8_t *manufacture_data = NULL;
                 uint8_t manufacture_data_len = 0;
                 manufacture_data = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE, &manufacture_data_len);
                 if(manufacture_data_len>16){					
                     app_bridged_device_t *device;
                     device = app_bridge_get_device_by_espnow_macaddr(param->scan_rst.bda);
                     if(device){
                         if(device->dev_info.device_status != manufacture_data[3])
                         {						
                             ESP_LOGI(GATTC_TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", ESP_BD_ADDR_HEX(param->scan_rst.bda));
                             ESP_LOGI(GATTC_TAG, "manufacture_data_len = %d", manufacture_data_len);
                             device->dev_info.device_status = manufacture_data[3];													
                             esp_log_buffer_hex(GATTC_TAG,manufacture_data,manufacture_data_len);	
                             DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockAttribute, reinterpret_cast<intptr_t>(device));
                         }
                     }
                 }						
             }
             break;
         case ESP_GAP_SEARCH_INQ_CMPL_EVT:
             break;
         default:
             break;
         }
         break;
     }
 
     case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
         if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
             ESP_LOGE(GATTC_TAG, "scan stop failed, error status = %x", param->scan_stop_cmpl.status);
             break;
         }
         ESP_LOGI(GATTC_TAG, "stop scan successfully");
         break;
 
     case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
         if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
             ESP_LOGE(GATTC_TAG, "adv stop failed, error status = %x", param->adv_stop_cmpl.status);
             break;
         }
         ESP_LOGI(GATTC_TAG, "stop adv successfully");
         break;
     case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
          ESP_LOGI(GATTC_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
                   param->update_conn_params.status,
                   param->update_conn_params.min_int,
                   param->update_conn_params.max_int,
                   param->update_conn_params.conn_int,
                   param->update_conn_params.latency,
                   param->update_conn_params.timeout);
         break;
     default:
         break;
     }
 }
 #endif
 */
 
 
 static int blecent_gap_event(struct ble_gap_event *event, void *arg);
 
 
 static void blecent_connect_if_interesting()
 {
     uint8_t own_addr_type;
     ble_addr_t peer_addr;
     int rc;
     uint8_t addr_val[6] = {0x25, 0xed, 0xe2, 0x36, 0xce, 0xf4};
 
 
     /* Scanning must be stopped before a connection can be initiated. */
     rc = ble_gap_disc_cancel();
     if (rc != 0) {
         MODLOG_DFLT(DEBUG, "Failed to cancel scan; rc=%d\n", rc);
         return;
     }
 
     peer_addr.type = BLE_ADDR_PUBLIC; 
     memcpy(peer_addr.val, addr_val, sizeof(addr_val));
 
     rc = ble_gap_connect(BLE_OWN_ADDR_RANDOM, &peer_addr, 30000, NULL,
                          blecent_gap_event, NULL);
     if (rc != 0)
     {
         MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d "
                            "addr=%s; rc=%d\n",
                     peer_addr.type, addr_str(peer_addr.val), rc);
         return;
     }
 }
 
 
 
 
 
 // 定义需要查找的服务和特征 UUID
 static const ble_uuid16_t svc_uuid = BLE_UUID16_INIT(0xFFF0);
 static const ble_uuid16_t chr_write_uuid = BLE_UUID16_INIT(0xFFF1);
 static const ble_uuid16_t chr_notify_uuid = BLE_UUID16_INIT(0xFFF4);
 
 // 保存发现到的句柄
 static uint16_t svc_start_handle, svc_end_handle;
 static uint16_t chr_write_handle, chr_notify_handle;
 
 
 /**
  * Application callback.  Called when the attempt to subscribe to notifications
  * for the ANS Unread Alert Status characteristic has completed.
  */
 static int
 blecent_on_subscribe(uint16_t conn_handle,
                      const struct ble_gatt_error *error,
                      struct ble_gatt_attr *attr,
                      void *arg)
 {
     struct peer *peer;
 
     MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d "
                 "attr_handle=%d\n",
                 error->status, conn_handle, attr->handle);
 
     
 
     return 0;
 }
 
 // 写入完成回调函数
 static int on_write_complete(uint16_t conn_handle, const struct ble_gatt_error *error,
                   struct ble_gatt_attr *attr, void *arg)
 {
     if (error->status == 0)
     {
         printf("fff1写入成功\n");
     }
     else
     {
         printf("写入失败，错误码：%d\n", error->status);
     }
     return 0;
 }
 
 // 特征发现回调函数
 static int chr_disc_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
                          struct ble_gatt_chr *chr, void *arg)
 {
     if (error->status != 0) {
         printf("特征发现错误，错误码: %d\n", error->status);
         return error->status;
     }
 
     // 将特征 UUID 转换为字符串用于打印
     char uuid_str[BLE_UUID_STR_LEN];
     ble_uuid_to_str(&chr->uuid.u, uuid_str);
     printf("发现特征：UUID = %s, value_handle = 0x%04X\n",
            uuid_str, chr->val_handle);
 
 
     if (!strcmp("0xfff4", uuid_str))
     {
         // 发起订阅通知
         uint8_t cccd_value[2] = {0x01, 0x00}; // 启用通知
         int rc = ble_gattc_write_flat(conn_handle, chr->val_handle,
                                       cccd_value, sizeof(cccd_value), blecent_on_subscribe, NULL);
         if (rc != 0)
         {
             printf("订阅通知失败，错误码: %d\n", rc);
         }
         else
         {
             printf("成功订阅通知\n");
         }
     }
     else if(!strcmp("0xfff1", uuid_str))
     {
        
 
         // 要写入的数据
         uint8_t data[] = {0xA1, 0xB2, 0xC3, 0xD4, 0x09, 0x00, 0x01, 0x0F, 0xF3};
 
         // 
         // 写入特征值
         int rc = ble_gattc_write_flat(conn_handle, chr->val_handle, data, sizeof(data),
                                   on_write_complete, NULL);
 
         printf("gaoyuezheng 这里发消息 fff1 rc = %d\n",rc);
     }
 
 
     return 0;
 }
 
 
 
 // 服务发现回调函数
 static int svc_disc_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
                        struct ble_gatt_svc *service, void *arg)
 {
     if ((error->status != 0)) {
         printf("服务发现错误，错误码：%d\n", error->status);
         return error->status;
     }
     
     // 此处可以对每个发现的服务进行处理，例如打印服务 UUID 和句柄范围
     char uuid_str[BLE_UUID_STR_LEN];
     ble_uuid_to_str(&service->uuid.u, uuid_str);
     printf("发现服务：UUID = %s, start_handle = 0x%04X, end_handle = 0x%04X\n",
            uuid_str, service->start_handle, service->end_handle);
     
 
     if(!strcmp(uuid_str,"0xfff0"))
     {
         
         // 服务发现完成后，启动特征发现
         printf("服务发现完成，开始特征发现...\n");
         // int rc = ble_gattc_disc_chrs_by_uuid(conn_handle,
         //                                      service->start_handle,
         //                                      service->end_handle,
         //                                      (ble_uuid_t *)&chr_notify_uuid,
         //                                      chr_disc_cb,
         //                                      NULL);
 
         int rc = ble_gattc_disc_all_chrs(conn_handle,
                                              service->start_handle,
                                              service->end_handle,
                                              chr_disc_cb,
                                              NULL);
 
         if (rc != 0)
         {
             printf("启动按 UUID 发现特征失败，错误码: %d\n", rc);
         }
         else
         {
             printf("正在根据 UUID 查找特征...\n");
         }
     }
     return 0;
 }
 
 
 
 static int blecent_gap_event(struct ble_gap_event *event, void *arg)
 {
     struct ble_hs_adv_fields fields;
     int rc;	
     app_bridged_device_t *device;
     uint8_t espnow_macaddr[6];
     struct ble_gap_conn_desc desc;
     switch (event->type) {
         
     case BLE_GAP_EVENT_DISC:
             espnow_macaddr[0] = event->disc.addr.val[5];
             espnow_macaddr[1] = event->disc.addr.val[4];
             espnow_macaddr[2] = event->disc.addr.val[3];
             espnow_macaddr[3] = event->disc.addr.val[2];
             espnow_macaddr[4] = event->disc.addr.val[1];
             espnow_macaddr[5] = event->disc.addr.val[0];
             device = app_bridge_get_device_by_espnow_macaddr(espnow_macaddr);
             /*
             if(device){
                  ESP_LOGE(GATTC_TAG, "Found Device (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                      event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);						
                  esp_log_buffer_hex(TAG,event->disc.data,event->disc.length_data);
             }
             */
 
             rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
                                          event->disc.length_data);
             if (rc != 0) {
                 if(device)
                     ESP_LOGE(TAG, "Failed to parse advertisement data; rc=%d\n", rc);
                 return 0;
             }/*else{
                 // if(device){
                 // 	ESP_LOGE(GATTC_TAG, "Found Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                 // 			event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);						
                 // 	esp_log_buffer_hex(GATTC_TAG,fields.mfg_data,fields.mfg_data_len);	
                 // }
             }*/
             if (fields.mfg_data_len>16){
                 // app_bridged_device_t *device;
                 // uint8_t espnow_macaddr[6];
                 // espnow_macaddr[0] = event->disc.addr.val[5];
                 // espnow_macaddr[1] = event->disc.addr.val[4];
                 // espnow_macaddr[2] = event->disc.addr.val[3];
                 // espnow_macaddr[3] = event->disc.addr.val[2];
                 // espnow_macaddr[4] = event->disc.addr.val[1];
                 // espnow_macaddr[5] = event->disc.addr.val[0];
                 //device = app_bridge_get_device_by_espnow_macaddr(espnow_macaddr);		
                 if(device){	
                     device->dev_info.rssi= event->disc.rssi;					
                     if((device->dev_info.is_online==false)||(get_timestamp_ms() - device->dev_info.last_update_time >120000)){
                         device->dev_info.is_online = true;
                         DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(device));
                         GetAppTask().AppScheduleWork(PublishOnlineStatus, reinterpret_cast<intptr_t>(device));  					
                     }
                     device->dev_info.last_update_time = get_timestamp_ms();
                     if(fields.mfg_data[2]==19){
                         if(fields.mfg_data[21]==1){
                             GetAppTask().AppScheduleWork(SendLockSyncTimeCommand, reinterpret_cast<intptr_t>(device)); 
                         }
                     }
 
                     if(memcmp(device->dev_info.ble_broadcast_data,fields.mfg_data,fields.mfg_data_len))
                     {
                         ESP_LOGE(GATTC_TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                             event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);						
                         // ESP_LOGI(GATTC_TAG, "manufacture_data_len = %d", fields.mfg_data_len);
                         // esp_log_buffer_hex(GATTC_TAG,fields.mfg_data,fields.mfg_data_len);	
                         device->dev_info.change_bit=0;
                         if(device->dev_info.device_status!=fields.mfg_data[3]){			
                             if((device->dev_info.device_status&0x01)!=(fields.mfg_data[3]&0x01))
                                 device->dev_info.change_bit |=DoorLockStatusBit;
                             device->dev_info.last_change_time = get_timestamp_ms();
                             if(fields.mfg_data[3]&0x02)
                             {
                                 // to do .. find the wired sensor firstly								
                                 app_bridged_device_t *sensor = app_bridge_get_sensor_by_sensor_id("FFFFFF");
                                 if((sensor)&&((device->dev_info.device_status&0x04)!=(fields.mfg_data[3]&0x04))){
                                     if(fields.mfg_data[3]&0x04)
                                         sensor->dev_info.sensor_status = 1;		
                                     else
                                         sensor->dev_info.sensor_status = 2;							
                                     sensor->dev_info.last_change_time = get_timestamp_ms();	
                                     if(ENABLE_HOMEKIT_SENSOR)	
                                         DeviceLayer::PlatformMgr().ScheduleWork(UpdateDoorSensorAttribute, reinterpret_cast<intptr_t>(sensor));			
                                     else
                                         ESP_LOGE(TAG, "Sensor status is %d, HOMEKIT sesnor function is disabled.",sensor->dev_info.sensor_status);
                                     //Commented by Tony Wei. 2024.07.74
                                     //For wired sensor, no need to push sensor message. Only publish lock status, and let mbps to handel push message									
                                     //GetAppTask().AppScheduleWork(PublishDoorSensorStatus,  reinterpret_cast<intptr_t>(sensor)); 									
                                     //Commented by Tony Wei. 2024.07.74
                                     device->dev_info.change_bit |=DoorLockStatusBit;
                                     if(sensor->dev_info.is_online == false){
                                         sensor->dev_info.is_online = true;
                                         DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(sensor));
                                     }
                                 }
                             }		
 
                             ESP_LOGE(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                                 event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);
                             ESP_LOGE(TAG, "Old Status:%02x, New Status:%02x",device->dev_info.device_status,fields.mfg_data[3]);
 
                             if(((device->dev_info.device_status&(SECURE_MODE_BIT | SECURE_MODE_BIT))!=(fields.mfg_data[3]&(SECURE_MODE_BIT | SECURE_MODE_BIT)))
                                ||((device->dev_info.device_status&LOW_BAT_BIT)!=(fields.mfg_data[3]&LOW_BAT_BIT))){
                                 if(fields.mfg_data[3]&(SECURE_MODE_BIT | SECURE_MODE_BIT))
                                     ESP_LOGE(TAG, "Secure Mode is on");
                                 else
                                     ESP_LOGE(TAG, "Secure Mode is off");
                                     
                                 if(fields.mfg_data[3]&(LOW_BAT_BIT)){
                                     ESP_LOGE(TAG, "Low Battery");
                                 }
                                 else{
                                     ESP_LOGE(TAG, "Battery is normal");								
                                 }
                                 device->dev_info.change_bit |=DoorLockStatusBit;
                             }
 
                             if((device->dev_info.device_status&0x01)!=(fields.mfg_data[3]&0x01))
                             {
                                 device->dev_info.device_status = fields.mfg_data[3];
                                 device->dev_info.reserve[0] = 0;
                                 device->dev_info.reserve[0] = 0;
                                 device->dev_info.reserve[0] = 0;
                                 DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockAttribute, reinterpret_cast<intptr_t>(device));
                             }
                             else
                                 device->dev_info.device_status = fields.mfg_data[3];							
 
 
                         }
                         if(memcmp(&device->dev_info.ble_broadcast_data[4],&fields.mfg_data[4],fields.mfg_data_len-4)){								
                             device->dev_info.change_bit |=DoorlockEventBit;
                         }
                         memcpy(device->dev_info.ble_broadcast_data,fields.mfg_data,fields.mfg_data_len);						
                         if(device->dev_info.change_bit)
                             GetAppTask().AppScheduleWork(PublishDoorLockStatus, reinterpret_cast<intptr_t>(device));
                     }else{
                         blecent_connect_if_interesting();  
                         // blecent_connect();   // 这里筛选要连接的从机
                     /*
                         ESP_LOGE(GATTC_TAG, "Data No Change: Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", event->disc.addr.val[5],\
                             event->disc.addr.val[4],event->disc.addr.val[3],event->disc.addr.val[2],event->disc.addr.val[1],event->disc.addr.val[0]);						
                         esp_log_buffer_hex(GATTC_TAG,fields.mfg_data,fields.mfg_data_len);
                     */ 
                     }
                 }
             }
             else{
                 //ESP_LOGE(GATTC_TAG, "No manufacture data");
                 app_bridged_device_t *device;
                 uint8_t espnow_macaddr[6];
                 espnow_macaddr[0] = event->disc.addr.val[5];
                 espnow_macaddr[1] = event->disc.addr.val[4];
                 espnow_macaddr[2] = event->disc.addr.val[3];
                 espnow_macaddr[3] = event->disc.addr.val[2];
                 espnow_macaddr[4] = event->disc.addr.val[1];
                 espnow_macaddr[5] = event->disc.addr.val[0];
                 device = app_bridge_get_device_by_espnow_macaddr(espnow_macaddr);	
                 if(device){
                     device->dev_info.rssi= event->disc.rssi;					
                     if((device->dev_info.is_online==false)||(get_timestamp_ms() - device->dev_info.last_update_time >120000)){
                         device->dev_info.is_online = true;
                         DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(device));
                         GetAppTask().AppScheduleWork(PublishOnlineStatus, reinterpret_cast<intptr_t>(device));  					
                     }		
                     device->dev_info.last_update_time = get_timestamp_ms();
                 }
             }
     
         return 0;
 
     case BLE_GAP_EVENT_NOTIFY_RX:
         /* Peer sent us a notification or indication. */
         MODLOG_DFLT(INFO, "received %s; conn_handle=%d attr_handle=%d "
                     "attr_len=%d\n",
                     event->notify_rx.indication ?
                     "indication" :
                     "notification",
                     event->notify_rx.conn_handle,
                     event->notify_rx.attr_handle,
                     OS_MBUF_PKTLEN(event->notify_rx.om));
 
         /* Attribute data is contained in event->notify_rx.om. Use
          * `os_mbuf_copydata` to copy the data received in notification mbuf */
         // 接收到 0x06 0x88 ,回复从机 当前获取的rssi的值
 
         MODLOG_DFLT(INFO, "rev data form pher = %02x %02x data len = %d", event->notify_rx.om->om_data[0], event->notify_rx.om->om_data[1], event->notify_rx.om->om_len);
 
         return 0;
 
     case BLE_GAP_EVENT_CONNECT:
 
         if (event->connect.status == 0)
         {
             /* Connection successfully established. */
             MODLOG_DFLT(INFO, "yuzheng.gao Connection established ");
 
             printf("连接成功，句柄：%d\n", event->connect.conn_handle);
             // 连接成功后启动服务发现
             int rc = ble_gattc_disc_all_svcs(event->connect.conn_handle,
                                              svc_disc_cb,
                                              NULL);
             // ble_gattc_disc_svc_by_uuid 根据UUID 发现服务
             if (rc)
             {
                 printf("启动服务发现失败，错误码：%d\n", rc);
             }
             return 0;
         }
         else
         {
             /* Connection attempt failed; resume scanning. */
             MODLOG_DFLT(ERROR, "Error: Connection failed; status=%d\n",
                         event->connect.status);
             // blecent_scan();
         }
 
     default:
         return 0;
     }
 }
 
 
 
 
 void AppTask::ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction)
 {
     if (btnIdx != APP_FUNCTION_BUTTON)
     {
         return;
     }
 
     AppEvent button_event             = {};
     button_event.Type                = AppEvent::kEventType_Button;
     button_event.ButtonEvent.mPinNo  = btnIdx;
     button_event.ButtonEvent.mAction = btnAction;
     button_event.Handler = FunctionHandler;
     sAppTask.PostEvent(&button_event);
 
 }
 
 void AppTask::RestartTimerEventHandler(TimerHandle_t xTimer){
     // Call the function to restart the system
     ESP_LOGE(TAG, "----------Restarting the system in the timer callback-----------");
     esp_restart();
     
 }
 
 void AppTask::InitWatchdogEventHandler(TimerHandle_t xTimer){
     // Call the function to restart the system
     //esp_restart();
     if(is_mqtt_connected()){
         ESP_LOGE(TAG, "MQTT init success");
         ESP_LOGE(TAG, "Cancel watchdo timer");
         if (xTimerStop(sInitWatchdogTimer, 0) == pdFAIL)
         {
             ESP_LOGI(TAG, "InitWatchdog timer stop() failed");
         }
     }
     else{
         ESP_LOGE(TAG, "MQTT init failed");
         ESP_LOGE(TAG, "Restarting the system in the timer callback");
     }
 }
 
 void AppTask::ScanDevTimerEventHandler(TimerHandle_t xTimer)
 {
     AppEvent event;
     event.Type                = AppEvent::kEventType_ScanDevTimer;
     event.TimerEvent.Context = (void *) xTimer;
     event.Handler             = ScanDevFunctionTimerEventHandler;
     sAppTask.PostEvent(&event);
 
 }
 void AppTask::ScanDevFunctionTimerEventHandler(AppEvent * aEvent)
 {
 #ifdef CONFIG_BT_BLUEDROID_ENABLED
     
     int ret = esp_ble_gap_register_callback(esp_gap_cb);
     if (ret){
         ESP_LOGE(TAG, "%s gap register failed, error code = %x\n", __func__, ret);
         return;
     }
 
     static esp_ble_scan_params_t ble_scan_params = {    .scan_type              = BLE_SCAN_TYPE_ACTIVE,
                                                         .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,
                                                         .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,//BLE_SCAN_FILTER_ALLOW_ONLY_WLST,//BLE_SCAN_FILTER_ALLOW_ALL,
                                                         .scan_interval          = 0x28,
                                                         .scan_window            = 0x24};	
     
 
     int rc = esp_ble_gap_set_scan_params(&ble_scan_params);
     if (rc != 0)
     {
         ESP_LOGE(TAG, "esp_ble_gap_set_scan_params failed: %d", rc);
     }
 #endif
 
 #ifdef CONFIG_BT_NIMBLE_ENABLED
     uint8_t own_addr_type;
     struct ble_gap_disc_params disc_params;
     int rc;
 
     /* Figure out address to use while advertising (no privacy for now) */
     rc = ble_hs_id_infer_auto(0, &own_addr_type);
     if (rc != 0) {
         ESP_LOGE(TAG, "error determining address type; rc=%d\n", rc);
         return;
     }
 
     /* Tell the controller to filter duplicates; we don't want to process
      * repeated advertisements from the same device.
      */
     disc_params.filter_duplicates = 1;
 
     /**
      * Perform a passive scan.  I.e., don't send follow-up scan requests to
      * each advertiser.
      */
     disc_params.passive = 0;
 
     /* Use defaults for the rest of the parameters. */
     disc_params.itvl = 500;
     disc_params.window = 450;
     disc_params.filter_policy = 0;
     disc_params.limited = 0;
 
     ESP_LOGI(TAG, "Use nimble ble scan\n");
     rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params,
                       blecent_gap_event, NULL);
     if (rc != 0) {
         ESP_LOGE(TAG, "Error initiating GAP discovery procedure; rc=%d\n",
                     rc);
     }
     if (xTimerIsTimerActive(sScanDevTimer))
     {
         ESP_LOGI(TAG, "ScanDev timer stop!");
         if (xTimerStop(sScanDevTimer, 0) == pdFAIL)
         {
             ESP_LOGI(TAG, "ScanDev timer stop() failed");
         }
     }		
 #endif
 
 }
 
 void AppTask::ResetToFactory(void)
 {
     ESP_LOGI(TAG, "ResetToFactory");
     factory_reset();
     //chip::Server::GetInstance().ScheduleFactoryReset();
 }
 
 uint64_t last_matter_timestamp = 0;
 void AppTask::FunctionHandler(AppEvent * aEvent)
 {
     if (aEvent->ButtonEvent.mPinNo != APP_FUNCTION_BUTTON)
     {
         return;
     }
 
     // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (<
     // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the
     // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT +
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after
     // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs
     // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     if (aEvent->ButtonEvent.mAction == APP_BUTTON_LONGPRESSED)
     {
         ESP_LOGW(TAG, "APP_BUTTON_LONGPRESSED");
         if ((xTaskGetTickCount() * portTICK_PERIOD_MS) < FACTORY_RESET_BUTTON_AVAIABLE_WINDOW) // 在上电调度的前20s
         {
             ESP_LOGW("yuezheng.gao", "-----kFunction_FactoryReset-----");
             // Actually trigger Factory Reset
             // sAppTask.mFunction = kFunction_NoneSelected;
             // GetAppTask().ResetToFactory();
             chip::Server::GetInstance().ScheduleFactoryReset(); // 这个不会删除 endpiont
             // esp_matter::factory_reset();    // 这个恢复出场设置会把所有的endpiont都删除
         }
         else
         {
             app_matter_open_commissioning();
         }
     }
     else if (aEvent->ButtonEvent.mAction == APP_BUTTON_RELEASED)
     {
         ESP_LOGW(TAG, "APP_BUTTON_RELEASED");
 
        
 
         if (!ConnectivityMgr().IsWiFiStationProvisioned())
         {
             ESP_LOGW(TAG, "Network is not provisioned, Ble advertissement enabled"); // 在配网状态下 按下按键 再次启动快速广播
             chip::DeviceLayer::PlatformMgr().LockChipStack();
             // Enable BLE advertisements
             chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
             ConnectivityMgr().SetBLEAdvertisingEnabled(true);
             ConnectivityMgr().SetBLEAdvertisingMode(ConnectivityMgr().kFastAdvertising);
             chip::DeviceLayer::PlatformMgr().UnlockChipStack();
         }
     }
     else if(aEvent->ButtonEvent.mAction == APP_BUTTON_DOUBLE_CLICK)
     {
         ESP_LOGW(TAG, "APP_BUTTON_DOUBLE_CLICK  the IsMatterCommissioned() = %d is wifi connected = %d",IsMatterCommissioned(),ConnectivityMgr().IsWiFiStationConnected());
         // wificonfig();
         // wifi_configuration();
         // GetAppTask().PostBlePairForWifiConnect();
         get_wifi_status();
     }
 }
 
 bool AppTask::isStartedWifiProvioning(void){
     return startedWifiProvioning;
 }
 
 void AppTask::setStartedWifiProvioning(bool value){
     startedWifiProvioning = value;
 }
 
 void AppTask::IdentifyActionEventHandler(AppEvent * aEvent)
 {
     unsigned int Length;
     unsigned char *buffer;	
     PGCDate syncTime;
 
     //ESP_LOGI(TAG, "++++IdentifyAction: EndpointID: %u, type: %u", aEvent->IdentifyEvent.EndpointID, aEvent->IdentifyEvent.type);
 
     ESP_LOGE(TAG, "IdentifyActionEventHandler: EndpointID: %u, type: %u", aEvent->IdentifyEvent.EndpointID, aEvent->IdentifyEvent.type);
     if(aEvent->IdentifyEvent.type==0){
         isIdentifying =1;
         sGreenLED.Set(false);
         sRedLED.Set(true);			
     }
     else if(aEvent->IdentifyEvent.type==1){
         isIdentifying =0;
         sGreenLED.Set(false);
         sRedLED.Set(true);		
     }
 
     app_bridged_device_t *current_device = app_bridge_get_device_by_matter_endpointid(aEvent->IdentifyEvent.EndpointID);
     if(current_device){
         if(current_device->dev->persistent_info.device_type_id==ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_ID)
         {					
             updatePgAesKey((const unsigned char *)current_device->dev_info.master_code,MASTER_CODE_LEN,(const unsigned char *)current_device->dev_info.device_uuid,(DEVICE_UUID_LEN * 2));
             //ESP_LOGI(TAG, "IdentifyActionEventHandler syncTime(before): %02x-%02x-%02x %02x:%02x:%02x", syncTime.year,syncTime.month,syncTime.day,syncTime.hour,syncTime.minute,syncTime.second);
             memset(&syncTime,0,sizeof(PGCDate));
             ESP_LOGI(TAG, "IdentifyActionEventHandler syncTime(after): %02x-%02x-%02x %02x:%02x:%02x", syncTime.year,syncTime.month,syncTime.day,syncTime.hour,syncTime.minute,syncTime.second);
             buffer = encodeCheckLockStateCmd(&Length,syncTime,PGCEnType_master,PGCCmdSrc_bt);		
             UartSendParm parm;
             parm.handler = CheckLockStateCmdHandler;
             uart_sent_ble_data((esp_bd_addr_t *)current_device->dev_addr.espnow_macaddr, buffer, Length, 10000,8,NULL,parm);
             free(buffer);
         }
     }else{
         ESP_LOGI("IdentifyActionEventHandler","current_device is NULL, identify bridge itself");
     }
 }
 
 
 void AppTask::LockActionEventHandler(AppEvent * aEvent)
 {
    unsigned int Length;
    unsigned char *buffer;     
    app_bridged_device_t *Device=NULL;
    UartSendParm parm;
    PGCDate syncTime;
 
 
    
    ESP_LOGI(TAG, "LockActionEventHandler, lock endpoint: 0x%x, lock status: 0x%x", aEvent->LockEvent.EndpointID,aEvent->LockEvent.Action);
    uint64_t timestamp = get_timestamp_ms();
    last_matter_timestamp = timestamp;
 
    Device = app_bridge_get_device_by_matter_endpointid((uint16_t)aEvent->LockEvent.EndpointID);
    if(Device){
        WakeupDoorLock(Device);
        updatePgAesKey((const unsigned char *)Device->dev_info.master_code,MASTER_CODE_LEN,(const unsigned char *)Device->dev_info.device_uuid,(DEVICE_UUID_LEN * 2));
         setRandomData((unsigned char *)&timestamp);
         /*buffer =adapterOpenCloseCmd(PGLockType(Device->dev_info.lock_type),
                                        (const char *)Device->dev_info.firmware_version,
                                        &Length,
                                        2,
                                        (unsigned char *)Device->dev_info.password,
                                        strlen((char *)Device->dev_info.password),
                                        0,
                                        0,
                                        (bool)aEvent->LockEvent.Action,
                                        PGCCmdSrc_alexa,
                                        PGCEnType_alexa);*/
         buffer =adapterOpenCloseCmdType(PGCCmdType(Device->dev_info.command_type),
                                                &Length,
                                                2,
                                                (unsigned char *)Device->dev_info.password,
                                                strlen((char *)Device->dev_info.password),
                                                0,
                                                0,
                                                (bool)aEvent->LockEvent.Action,
                                                PGCCmdSrc_alexa,
                                                PGCEnType_alexa);		
         bool unLock;
         PGCResult Result = decodeOpenCloseCmdFlag(&unLock,
                              buffer,
                              Length,
                              (const unsigned char *)Device->dev_info.master_code,
                              MASTER_CODE_LEN,
                              (const unsigned char *)Device->dev_info.device_uuid,
                              (DEVICE_UUID_LEN * 2),
                              (const unsigned char *)Device->dev_info.password,
                              strlen((char *)Device->dev_info.password));	
 
         if(Result.success){
             parm.command = unLock; 	
             parm.handler = CheckOpenCloseCmdHandler;
         }
         else{
             parm.handler = NULL;
         }
         uart_sent_ble_data((esp_bd_addr_t *)Device->dev_addr.espnow_macaddr, buffer, Length, 10000,2,NULL,parm);							   
         free(buffer);
        }
 
 }
 
 void restartAfterProvisioning(intptr_t context)
 {
     ESP_LOGI(TAG, "restartAfterProvisioning");
     if(startedWifiProvioning){
         if(ConnectivityMgr().IsWiFiStationProvisioned()){
 
             uint32_t free_heap_size = (uint32_t)esp_get_free_heap_size();
             if(free_heap_size<20000l){
                 ESP_LOGE(TAG, "Memory is to low, restarting in 2 seconds...");
                 vTaskDelay(2000 / portTICK_PERIOD_MS);
                 esp_restart();
             }
             else{
                 ESP_LOGE(TAG, "There is enough memory, not need to restart");
             }
         }
     }				
 }
 
 void StartRestartTimerAfterProvisioning(intptr_t context)
 {
     if(startedWifiProvioning){
         if(ConnectivityMgr().IsWiFiStationProvisioned()){            
             uint32_t free_heap_size = (uint32_t)esp_get_free_heap_size();
             ESP_LOGI(TAG, "---------------------------After provisioing: heap space  %" PRIu32 " -------", free_heap_size);
             if(free_heap_size<20000l){
                 if (sRestartTimer==NULL)
                     ESP_LOGE(TAG, "RestartTimer NULL");
                 else{
                     //xTimerStart(sRestartTimer, 0);										
                     if (xTimerIsTimerActive(sRestartTimer))
                     {
                         ESP_LOGI(TAG, "app timer already started, stop first!");
                         if (xTimerStop(sRestartTimer, 0) == pdFAIL)
                         {
                             ESP_LOGI(TAG, "sRestartTimer  stop() failed");
                             return;
                         }
                     } 					
                     // timer is not active, change its period to required value (== restart).
                     // FreeRTOS- Block for a maximum of 100 ticks if the change period command
                     // cannot immediately be sent to the timer command queue.
                     if (xTimerChangePeriod(sRestartTimer, 1800000 / portTICK_PERIOD_MS, 100) != pdPASS)
                     {
                         ESP_LOGI(TAG, "app timer start() failed");
                         return;
                     }
 
                 }
                 
             }
             else{
                 ESP_LOGE(TAG, "There is enough memory, not need to restart");
             }
         }
     }		
 }
 
 void AppTask::BridgedDevNumEventHandler(AppEvent * aEvent)
 {	
     unsigned int Length;
     unsigned char *buffer;	
     PGCDate syncTime;
     ESP_LOGI(TAG, "BridgedDevNum: %d", aEvent->BridgedDevNumEvent.number);	
     GetAppTask().AppScheduleWork(PublishDeviceInfoReport, NULL); 
     if(aEvent->BridgedDevNumEvent.number>0){
         ScanDevFunctionTimerEventHandler(NULL);
         if (xTimerIsTimerActive(sScanDevTimer))
         {
             ESP_LOGI(TAG, "ScanDev timer already started!");
             if (xTimerStop(sScanDevTimer, 0) == pdFAIL)
             {
                 ESP_LOGI(TAG, "ScanDev timer stop() failed");
             }
         }
         ESP_LOGI(TAG, "ScanDev timer start!");
         if (xTimerChangePeriod(sScanDevTimer, (BLEScanTimeout_MS+1000)/ portTICK_PERIOD_MS, 100) != pdPASS)
         {
             ESP_LOGI(TAG, "ScanDev timer start() failed");
         }	
         
         app_bridged_device_t* current_device;
         current_device = app_bridge_get_bridged_device_list();
         while (current_device) {
             if ((current_device->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_LOCKLY) && current_device->dev){
                 if(current_device->dev->persistent_info.device_type_id==ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_ID)
                 {					
                     updatePgAesKey((const unsigned char *)current_device->dev_info.master_code,MASTER_CODE_LEN,(const unsigned char *)current_device->dev_info.device_uuid,(DEVICE_UUID_LEN * 2));
                     //ESP_LOGI(TAG, "BridgedDevNumEventHandler syncTime(before): %02x-%02x-%02x %02x:%02x:%02x", syncTime.year,syncTime.month,syncTime.day,syncTime.hour,syncTime.minute,syncTime.second);
                     memset(&syncTime,0,sizeof(PGCDate));
                     ESP_LOGI(TAG, "BridgedDevNumEventHandler syncTime(after): %02x-%02x-%02x %02x:%02x:%02x", syncTime.year,syncTime.month,syncTime.day,syncTime.hour,syncTime.minute,syncTime.second);
                     buffer = encodeCheckLockStateCmd(&Length,syncTime,PGCEnType_master,PGCCmdSrc_bt);		
                     UartSendParm parm;
                     parm.handler = CheckLockStateCmdHandler;
                     uart_sent_ble_data((esp_bd_addr_t *)current_device->dev_addr.espnow_macaddr, buffer, Length, 10000,8,NULL,parm);
                     free(buffer);
                     InitialiseDoorLockAttributes(current_device);
                     /*if(strlen(current_device->dev_info.time_zone)){
                         if(setenv("TZ", current_device->dev_info.time_zone, 1)!=0)
                             ESP_LOGE(TAG, "set time zone:%s error", current_device->dev_info.time_zone);
                         else{
                             ESP_LOGI(TAG, "set time zone:%s success", current_device->dev_info.time_zone);
                                tzset();
                         }
                     }	*/					
                 }
                 else if(current_device->dev->persistent_info.device_type_id==ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_ID)
                 {
                      InitialiseDoorSensorAttributes(current_device);
                 }
             }
             current_device = current_device->next;
         }
         
     }
     else{
         if (xTimerIsTimerActive(sScanDevTimer))
         {
             ESP_LOGI(TAG, "ScanDev timer stop!");
             if (xTimerStop(sScanDevTimer, 0) == pdFAIL)
             {
                 ESP_LOGI(TAG, "ScanDev timer stop() failed");
             }
         }	
     }
     //GetAppTask().AppScheduleWork(StartRestartTimerAfterProvisioning, NULL); 
 }
 
 void AppTask::ServiceInitActionEventHandler(AppEvent * aEvent)
 {
    static bool Serviceinitialised=0;
    if(Serviceinitialised==0){
        ESP_LOGI(TAG, "ServiceInitActionEventHandler, ServiceType: 0x%x", aEvent->ServiceInitEvent.ServiceType); 
        if(aEvent->ServiceInitEvent.ServiceType == 1){
             // ESP_LOGE("RESTART_TASK", "Restarting now.");
             // vTaskDelay(5000 / portTICK_PERIOD_MS);
             // esp_restart();
             app_sntp_init();
             vTaskDelay(pdMS_TO_TICKS(1000));
             ecdh_timer_init();
             // app_mqtt_init();
                // if (ConnectivityMgr().IsWiFiStationProvisioned()){
             //     sRedLED.Set(true);
             //     sGreenLED.Set(false);    // 这里的灯亮会导致启动的时候打乱红灯的闪烁
             // }else{
             // }
             Serviceinitialised = 1;
            }
        else{
                sRedLED.Set(false);
             sGreenLED.Set(true);
        }	   	
        }
 
 }
 
 void AppTask::MqttConnectedEventHandler(AppEvent * aEvent)
 {
     if(aEvent->MqttConnectedEvent.Connected == true){
         static bool initialised=0;	
         if(initialised==0){
             ESP_LOGI(TAG, "MqttConnectedEventHandler");  			
                rf_sensor_init();
             app_uart_init();
             uart_send_task_init();	
             GetAppTask().BridgedDevNumActionRequest(app_bridge_get_bridged_device_number());
             initialised = 1;
         }
         sGreenLED.Set(false);					
         set_mqtt_connected();
     }
     else{
         sGreenLED.Set(true);
         clear_secret_key();
     }
 }
 
 esp_err_t AppTask::PostMqttConnectedActionRequest(bool isConnected)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_MqttConnected;
     event.MqttConnectedEvent.Connected = isConnected;
     event.Handler           = MqttConnectedEventHandler;
     return PostEvent(&event);
 }
 
 void AppTask::PostLockActionRequest(chip::EndpointId aEndpointID, int8_t aAction)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_Lock;
     event.LockEvent.EndpointID  = aEndpointID;
     event.LockEvent.Action = aAction;
     event.Handler           = LockActionEventHandler;
     PostEvent(&event);
 }
 
 void AppTask::PostIdentifyActionRequest(chip::EndpointId aEndpointID, int8_t aType)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_Lock;
     event.IdentifyEvent.EndpointID  = aEndpointID;
     event.IdentifyEvent.type = aType;
     event.Handler           = IdentifyActionEventHandler;
     PostEvent(&event);
 }
 
 esp_err_t AppTask::PostMqttActionRequest(uint32_t len, uint8_t* buf)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_Mqtt;
     event.MqttEvent.len  = len;
     event.MqttEvent.buf = buf;
     event.Handler           = MqttEventHandler;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::PostUartActionRequest(uint32_t len, uint8_t* buf)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_Uart;
     event.UartEvent.len  = len;
     event.UartEvent.buf = buf;
     event.Handler           =UartReceiveEventHandler;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::PostRfActionRequest(uint32_t len, uint8_t* buf)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_Rf;
     event.RfEvent.len  = len;
     event.RfEvent.buf = buf;
     event.Handler           =RfReceiveEventHandler;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::PostBlePairForWifiConnect(void){
     AppEvent event;
     // event.Type              = AppEvent::kEventType_ServiceInit;
     // event.ServiceInitEvent.ServiceType  = type;
     event.Handler           =ble_pair_wifi_info_cfg;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::PostServiceInitActionRequest(uint8_t type)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_ServiceInit;
     event.ServiceInitEvent.ServiceType  = type;
     event.Handler           =ServiceInitActionEventHandler;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::BridgedDevNumActionRequest(uint8_t number)
 {
     AppEvent event;
     event.Type              = AppEvent::kEventType_BridgedDev;
     event.BridgedDevNumEvent.number  = number;
     event.Handler           = BridgedDevNumEventHandler;
     return PostEvent(&event);
 }
 
 esp_err_t AppTask::PostEvent(const AppEvent * aEvent)
 {
 
     if (sAppEventQueue != NULL)
     {
         BaseType_t status;
         if (xPortInIsrContext())
         {
             BaseType_t higherPrioTaskWoken = pdFALSE;
             status                         = xQueueSendFromISR(sAppEventQueue, aEvent, &higherPrioTaskWoken);
         }
         else
         {
             status = xQueueSend(sAppEventQueue, aEvent, (TickType_t)1);
         }
         if (!status)
             {
                 ESP_LOGE(TAG, "Failed to post event to app task event queue");
                 return ESP_FAIL;
             }
         else
             return ESP_OK;
     }
     else
     {
         ESP_LOGE(TAG, "Event Queue is NULL should never happen");
         return ESP_FAIL;
     }
 
 }
 
 void AppTask::DispatchEvent(AppEvent * aEvent)
 {
     if (aEvent->Handler)
     {
         aEvent->Handler(aEvent);
     }
     else
     {
         if(aEvent->Type == AppEvent::kEventType_WorkFunct)
             aEvent->CallWorkFunct.WorkFunct(aEvent->CallWorkFunct.Arg);
         else
             ESP_LOGI(TAG, "Event received with no handler. Dropping event.");
     }
 }
 
 esp_err_t AppTask::AppScheduleWork(AppWorkFunct workFunct, intptr_t arg)
 {
 
     AppEvent event;
     event.Type              		= AppEvent::kEventType_WorkFunct;
     event.CallWorkFunct.WorkFunct   = workFunct;
     event.CallWorkFunct.Arg			= arg;
     event.Handler					= NULL;
     return PostEvent(&event);	
 }
 
 void AppTask::MonitorOnlinestatus(void)
 {
     app_bridged_device_t *current_device = app_bridge_get_bridged_device_list();
     if(IsTimeSynchronized()==false)
         return;
     uint64_t now = get_timestamp_ms();
     static bool offline=0;
     while (current_device) {
         if ((current_device->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_LOCKLY) && current_device->dev){
             if(current_device->dev->persistent_info.device_type_id==ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_ID)
             {
                  if(current_device->dev_info.is_online &&\
                      (current_device->dev_info.last_update_time) &&\
                      (now - current_device->dev_info.last_update_time >1200000)){
                      current_device->dev_info.is_online =false;				
                     DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(current_device));
                      GetAppTask().AppScheduleWork(PublishOnlineStatus, reinterpret_cast<intptr_t>(current_device));					 	
                     offline = 1;
                  }
                 if((offline==1)&&(current_device->dev_info.last_update_time>0)&&(now - current_device->dev_info.last_update_time > 86400000)){			
                     ESP_LOGE(TAG, "Lock: %s No Response. Reset the hub", current_device->dev_info.device_uuid); 
                     esp_restart();
                 }
 //				 if(offline == 1)
 //				 	ble_scan_status_debug();
             }
             else if(current_device->dev->persistent_info.device_type_id==ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_ID)
             {
                  if(current_device->dev_info.is_online &&\
                      (current_device->dev_info.last_update_time) &&\
                      (now - current_device->dev_info.last_update_time >12*3600*1000)){
                      current_device->dev_info.is_online =false;				
                     //DeviceLayer::PlatformMgr().ScheduleWork(UpdateLockReachableAttribute, reinterpret_cast<intptr_t>(current_device));
                  }
             }
         }
         current_device = current_device->next;
     }
 }
 
 
 
 
 void app_mqtt_process(esp_mqtt_event_handle_t event_data)
 {
     ESP_LOGI(TAG, "app_mqtt_process");
     //ESP_LOGI(TAG, "TOPIC=%s", event_data->topic);
     
     uint8_t* buf = (uint8_t*) pvPortMalloc(event_data->data_len);
     if(buf){
         memcpy(buf, (uint8_t*)event_data->data, event_data->data_len);
         if(GetAppTask().PostMqttActionRequest(event_data->data_len, buf)==ESP_FAIL){
              vPortFree(buf);
              buf = NULL;
             }
     }else{
         ESP_LOGE(TAG, "app mqtt pvPortMalloc error");
     }
     
 }
 
 void app_mqtt_connected(bool isConnected)
 {
     GetAppTask().PostMqttConnectedActionRequest(isConnected);
 }
 
 void timestamp_to_string(uint64_t timestamp, char* buffer, size_t buffer_size) {
     time_t rawtime = (time_t)timestamp;
     struct tm * timeinfo;
 
     timeinfo = localtime(&rawtime);
 
     strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", timeinfo);
 }
 
 bool needPublishLockEvent(uint16_t event_code, bool from_app){
     if (event_code == LK_EVENT_CODE_CLOSEDOOR_BY_LOCKLY)
         return false;
     
     if (event_code == LK_EVENT_CODE_MAIN_OPEN
         ||event_code == LK_EVENT_CODE_CLOSEDOOR_BY_AUTOMODE){
         char buf1[40];
         char buf2[40];
         uint64_t curr_timestamp = get_timestamp_ms();
         timestamp_to_string(last_matter_timestamp, buf1, sizeof(buf1));
         timestamp_to_string(curr_timestamp, buf2, sizeof(buf2));
         ESP_LOGI(TAG, "last_matter_timestamp: %s, curr_timestamp: %s", buf1, buf2);
         //ESP_LOGI(TAG, "curr_timestamp(%l) - last_matter_timestamp(%l): %l", curr_timestamp, last_matter_timestamp, curr_timestamp - last_matter_timestamp);
         //ESP_LOGI(TAG, "curr_timestamp - last_matter_timestamp: %l", curr_timestamp - last_matter_timestamp);
         if(curr_timestamp - last_matter_timestamp < 10000)
             return false;
     }
 
     return true;
 }
 
 chip::app::Clusters::DoorLock::OperationSourceEnum getOperationSource(uint8_t status, uint16_t event_code, bool from_app){
     chip::app::Clusters::DoorLock::OperationSourceEnum opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kKeypad;
     if( !(status & 0x01))
         opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kManual;
 
     if(from_app){
         return chip::app::Clusters::DoorLock::OperationSourceEnum::kProprietaryRemote;
         last_matter_timestamp = 0;
     }
 
     switch(event_code) {
         case LK_EVENT_CODE_ONCE_PW:
         case LK_EVENT_CODE_KEYBOARD_OPEN:
         case LK_EVENT_CODE_KEYGUEST_OPEN:
         case LK_EVENT_CODE_KEYFAMILY_OPEN:
         case LK_EVENT_CODE_LGUESTONCE_PW:
         case LK_EVENT_CODE_LGUESTGUEST_OPEN:
         case LK_EVENT_CODE_LGUESTFAMILY_OPEN:
         case LK_EVENT_CODE_OACTIMERLIMIT_OPEN:
         case LK_EVENT_CODE_OACONETIMER_OPEN:
         case LK_EVENT_CODE_LGUESTOACTIMERLIMIT_OPEN:
         case LK_EVENT_CODE_LGUESTOACONETIMER_OPEN:
         case LK_EVENT_CODE_MULTIPLE_OPENDOOR:
         case LK_EVENT_CODE_EMPLOYEE_PASSWORD_OPENDOOR:
         case LOG_EVENT_CODE_ADMIN_MULTIPLE_OPENDOOR:
         case LOG_EVENT_CODE_STAFF_MULTIPLE_OPENDOOR:
         case LOG_EVENT_CODE_DIF_USER_MULTIPLE_OPENDOOR:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kKeypad;
             break;
 
         case LK_EVENT_CODE_KEY_OPEN:
         case LK_EVENT_CODE_CLOSEDOOR_BY_UP_HANDLE:
         case LK_EVENT_CODE_CLOSEDOOR_BY_DOWN_HANDLE:
         case LK_EVENT_CODE_OPENDOOR_BY_DOWN_HANDLE:		
         case LOG_EVENT_CODE_VIOLENCE_OPENDOOR:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kManual;
             break;
 
         case LK_EVENT_CODE_CLOSEDOOR_BY_TOUCHSCREEN:
         case LK_EVENT_CODE_CLOSEDOOR_BY_TOUCH_PGKEY:
         case LK_EVENT_CODE_CLOSEDOOR_BY_LOCKLY_KEY:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kButton;
             break;
 
         case LK_EVENT_CODE_CLOSEDOOR_BY_AUTOMODE:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kAuto;
             break;
 
         case LK_EVENT_CODE_ENTER_WELCOMEMODE:
         case LK_EVENT_CODE_EXIT_WELCOMEMODE:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kSchedule;
             break;
 
         case LK_EVENT_CODE_RFID:
         case LK_EVENT_CODE_LGUESTRFID:
         case LK_EVENT_CODE_TPUESTRFID:
         case LOG_EVENT_CODE_EBADGE_CARD_OPENDOOR_ONE:
         case LOG_EVENT_CODE_EBADGE_CARD_OPENDOOR_MULTIPLE:
         case LK_EVENT_CODE_EMPLOYEE_RFID_OPENDOOR:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kRfid;
             break;
 
         case LK_EVENT_CODE_FINGER:
         case LOG_EVENT_CODE_EMERGENCY_FP:
         case LK_EVENT_CODE_EMPLOYEE_FP_OPENDOOR:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kBiometric;
             break;
 
         case LK_EVENT_CODE_ZWAVEOPENDOOR:
         case LK_EVENT_CODE_EMPLOYEE_APP_OPENDOOR:
         case LK_EVENT_CODE_UNLOCK_EXIT_BUTTON:
         case LK_EVENT_CODE_CLOSEDOOR_BY_Z_WAVEE:
         case LOG_EVENT_CODE_OPENDOOR_BY_EBADGE:
         case LOG_EVENT_CODE_CLOSEDOOR_BY_EBADGE:
             opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kProprietaryRemote;
             break;
 
         default:
             break;
     }
     return opSource;
 }
 
 void UpdateLockAttribute(intptr_t context)
 {
     app_bridged_device_t *device;
     uint16_t endpointId;
     device = (app_bridged_device_t *)context;
     endpointId = esp_matter::endpoint::get_id(device->dev->endpoint);
         
     node_t *node = node::get();
     endpoint_t *endpoint = endpoint::get(node, endpointId);
     cluster_t *cluster = cluster::get(endpoint, DoorLock::Id);
     attribute_t *attribute = attribute::get(cluster, DoorLock::Attributes::LockState::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     chip::app::Clusters::DoorLock::DlLockState newLockState = chip::app::Clusters::DoorLock::DlLockState::kLocked;
     //chip::app::Clusters::DoorLock::OperationSourceEnum opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kKeypad;
     if(device->dev_info.device_status & 0x01){
         val.val.u8 = (uint8_t)chip::app::Clusters::DoorLock::DlLockState::kUnlocked;//2;
         newLockState = chip::app::Clusters::DoorLock::DlLockState::kUnlocked;
     }
     else{
         val.val.u8 = (uint8_t)chip::app::Clusters::DoorLock::DlLockState::kLocked;//1;
         //opSource = chip::app::Clusters::DoorLock::OperationSourceEnum::kManual;
     }			
     attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::LockState::Id, &val);	
 
 
     ble_broadcast_data ble_broadcast;
     if(device->dev_info.ble_broadcast_data[2]==16){
         ble_broadcast_data16_t *ble_broadcast16;			
         ble_broadcast16 = (ble_broadcast_data16_t *)device->dev_info.ble_broadcast_data;
         ble_broadcast.header = ble_broadcast16->header;			
         ble_broadcast.len = ble_broadcast16->len;
         ble_broadcast.status = ble_broadcast16->status;
         ble_broadcast.event_id = ble_broadcast16->event_id;
         ble_broadcast.pwd_id = ble_broadcast16->pwd_id;
         ble_broadcast.event_code = ble_broadcast16->event_code;
         memcpy(ble_broadcast.oac,ble_broadcast16->oac,10);
         ble_broadcast.user_id = 0xffff;			
     }
     else if(device->dev_info.ble_broadcast_data[2]==17){
         ble_broadcast_data17_t *ble_broadcast17;			
         ble_broadcast17 = (ble_broadcast_data17_t *)device->dev_info.ble_broadcast_data;		
         ble_broadcast.header = ble_broadcast17->header;			
         ble_broadcast.len = ble_broadcast17->len;
         ble_broadcast.status = ble_broadcast17->status;
         ble_broadcast.event_id = ble_broadcast17->event_id;
         ble_broadcast.pwd_id = ble_broadcast17->pwd_id;
         ble_broadcast.event_code = ble_broadcast17->event_code;
         memcpy(ble_broadcast.oac,ble_broadcast17->oac,10);					
         ble_broadcast.user_id = 0xffff;
     }
     else /*if(device->dev_info.ble_broadcast_data[2]==18)*/{
         ble_broadcast_data18_t *ble_broadcast18;			
         ble_broadcast18 = (ble_broadcast_data18_t *)device->dev_info.ble_broadcast_data;				
         ble_broadcast.header = ble_broadcast18->header;			
         ble_broadcast.len = ble_broadcast18->len;
         ble_broadcast.status = ble_broadcast18->status;
         ble_broadcast.event_id = ble_broadcast18->event_id;
         ble_broadcast.pwd_id = ble_broadcast18->pwd_id;
         ble_broadcast.event_code = ble_broadcast18->event_code;			
         ble_broadcast.user_id = ble_broadcast18->pwd_id;
         memcpy(ble_broadcast.oac,ble_broadcast18->oac,10);				
         ble_broadcast.pid_type = ble_broadcast18->pid_type;
     }
 
      ESP_LOGI(TAG, "-------------------UpdateLockAttribute: status=%u--------------------------",device->dev_info.device_status);
      ESP_LOGI(TAG, "Event: status=%u, event_id=%d, pwd_id=%d, event_code =%u, user_id=%u,pid_type=%u",
          ble_broadcast.status, ble_broadcast.event_id, ble_broadcast.pwd_id, ble_broadcast.event_code, ble_broadcast.user_id, ble_broadcast.pid_type);
 
     bool isAPP = false;
     if(device->dev_info.reserve[0]==65 //'A'
         &&device->dev_info.reserve[1]==80 //'P'
         &&device->dev_info.reserve[2]==80) //'P'
         isAPP = true;
     esp_log_buffer_hex(TAG,device->dev_info.reserve,sizeof(device->dev_info.reserve));
     
     if(needPublishLockEvent(ble_broadcast.event_code, isAPP)){				
         DoorLock::OperationSourceEnum opSource = getOperationSource(device->dev_info.device_status,ble_broadcast.event_code, isAPP);
         chip::EndpointId aEndpointID;
         memcpy(&aEndpointID, &endpointId, sizeof(uint16_t));
         
         ESP_LOGI(TAG, "UpdateLockAttribute, endpointId:%u, aEndpointID:%u",endpointId,aEndpointID);
 
         Nullable<uint16_t> userIndex; 
         Nullable<List<const LockOpCredentials>> userCredentials; 
         userCredentials.SetNull();
 
         if (opSource == DoorLock::OperationSourceEnum::kKeypad && 
             newLockState == DoorLock::DlLockState::kUnlocked) {
             //userIndex = (uint16_t)ble_broadcast.pwd_id;
             userIndex.SetNonNull((uint16_t)ble_broadcast.pwd_id);
             // 使用构造函数或方法初始化`credentials`
             LockOpCredentials userCredential[] = { { DoorLock::CredentialTypeEnum::kPin,(uint16_t)ble_broadcast.pwd_id } };
             ESP_LOGI(TAG, "UpdateLockAttribute, userIndex:%u",userIndex.Value());
             for (const auto& credential : userCredential) {
                 ESP_LOGI(TAG, "UpdateLockAttribute, credential type:%u, credential id:%u",(uint8_t)(credential.credentialType),credential.credentialIndex);
             }
 
             userCredentials.SetNonNull(List<const LockOpCredentials>(userCredential));			
             if(userCredentials.IsNull() == false){
                 auto credentialsList = userCredentials.Value();
                 for (const auto& credential : credentialsList) {
                     ESP_LOGI(TAG, "UpdateLockAttribute, credential type:%u, credential id:%u",(uint8_t)(credential.credentialType),credential.credentialIndex);
                 }
             }else{
                 ESP_LOGI(TAG, "UpdateLockAttribute, userCredentials:NULL");
             }
 
         } else if (opSource == DoorLock::OperationSourceEnum::kBiometric && 
             newLockState == DoorLock::DlLockState::kUnlocked) {
             //userIndex = (uint16_t)ble_broadcast.pwd_id;
             userIndex.SetNonNull((uint16_t)(ble_broadcast.pwd_id+100));
             ESP_LOGI(TAG, "ble_broadcast.pwd_id: %u", ble_broadcast.pwd_id);			
             uint16_t credentialIndex = ble_broadcast.pwd_id+100;
             ESP_LOGI(TAG, "UpdateLockAttribute, credentialIndex:%u",credentialIndex);
             LockOpCredentials userCredential[] = { { DoorLock::CredentialTypeEnum::kFingerprint, credentialIndex } };
             //userCredentials  = chip::app::DataModel::MakeNullable<List<const LockOpCredentials>>(userCredential);
             userCredentials.SetNonNull(List<const LockOpCredentials>(userCredential));
             if(userCredentials.IsNull() == false){
                 auto credentialsList = userCredentials.Value();
                 for (const auto& credential : credentialsList) {
                     ESP_LOGI(TAG, "UpdateLockAttribute, credential type:%u, credential id:%u",(uint8_t)(credential.credentialType),credential.credentialIndex);
                 }
             }else{
                 ESP_LOGI(TAG, "UpdateLockAttribute, userCredentials:NULL");
             }
 
         }
         if(userIndex.IsNull() == false){
             ESP_LOGI(TAG, "UpdateLockAttribute, userIndex:%u",userIndex.Value());
         }
         else
             ESP_LOGI(TAG, "UpdateLockAttribute, userIndex:NULL, userCredentials:NULL");
         DoorLockServer::Instance().SetLockState(aEndpointID, newLockState, opSource, userIndex, userCredentials);	
     }
     //GetAppTask().AppScheduleWork(PublishDoorLockStatus, context);	 
 }
 
 void UpdateLockReachableAttribute(intptr_t context)
 {
     app_bridged_device_t *device;
     uint16_t endpointId;
     device = (app_bridged_device_t *)context;
     endpointId = esp_matter::endpoint::get_id(device->dev->endpoint);		
     node_t *node = node::get();
     endpoint_t *endpoint = endpoint::get(node, endpointId);
     cluster_t *cluster = cluster::get(endpoint, BridgedDeviceBasicInformation::Id);
     attribute_t *attribute = attribute::get(cluster, BridgedDeviceBasicInformation::Attributes::Reachable::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     val.val.b = device->dev_info.is_online;		
     attribute::update(endpointId, BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::Reachable::Id, &val);	
 }
 
 void GotRtcTime(intptr_t context)
 {
     if (PlatformMgr().TryLockChipStack())
     {
         System::SystemClock().SetClock_RealTime(Microseconds64(get_timestamp_us()));	
         PlatformMgr().UnlockChipStack();
     }	
     GetAppTask().AppScheduleWork(PublishHubStatus, NULL); 
     app_mqtt_init();
 }
 
 uint32_t getFwVersionNumberFromString(uint8_t *versionStr)
 {
     int major, minor, patch;
     uint32_t versionNumber = 0;
 
     // 解析版本号字符串
     if (sscanf(versionStr, "%d.%d.%d", &major, &minor, &patch) != 3) {
         //fprintf(stderr, "Error: Invalid version string format.\n");
         ESP_LOGE(TAG, "Error: Invalid version string format:%s .", (char*)versionStr);
         return 0;  // 返回0表示错误
     }
 
     // 合并版本号成一个 uint32_t 数值
     versionNumber |= (major << 16);  // 主版本号
     versionNumber |= (minor << 8);   // 次版本号
     versionNumber |= patch;          // 修订号
 
     return versionNumber;
 }
 
 void InitialiseDoorLockAttributes(app_bridged_device_t* device)
 {
     cluster_t *cluster = cluster::get(device->dev->endpoint, DoorLock::Id);
     attribute_t *attribute = attribute::get(cluster, DoorLock::Attributes::LockState::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     if(val.val.u8 == (uint8_t)chip::app::Clusters::DoorLock::DlLockState::kUnlocked)
         device->dev_info.device_status |= 0x01;
     else if(val.val.u8 == (uint8_t)chip::app::Clusters::DoorLock::DlLockState::kLocked)
         device->dev_info.device_status &= ~(0x01);
 /*	
     cluster = cluster::get(device->dev->endpoint, BridgedDeviceBasicInformation::Id);
     attribute = attribute::get(cluster, BridgedDeviceBasicInformation::Attributes::Reachable::Id);
     val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     device->dev_info.is_online = val.val.b;		*/
     
     ESP_LOGE(TAG, "---------------InitialiseDoorLockAttributes-------------------------");
 
     ESP_LOGE(TAG, "InitialiseDoorLockAttributes, lock_status:%x,is_online:%x",device->dev_info.device_status,device->dev_info.is_online);
     char VenderName[32]="Lockly";
     val = esp_matter_char_str(VenderName, strlen(VenderName));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::VendorName::Id, &val);
     ESP_LOGI(TAG, "VenderName:%s",VenderName);
 
     val = esp_matter_char_str(device->dev_info.device_name, strlen(device->dev_info.device_name));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::SerialNumber::Id, &val);
     ESP_LOGI(TAG, "SerialNumber:%s",device->dev_info.device_name);
 
 //	char ProductName[32]="PGD628FN";
     if(strlen(device->dev_info.model)>0)
         val = esp_matter_char_str(device->dev_info.model, strlen(device->dev_info.model));	
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::ProductName::Id, &val);
 
     ESP_LOGI(TAG, "ProductName:%s",device->dev_info.model);
 
     if(strlen(device->dev_info.node_label)>0){
         val = esp_matter_char_str(device->dev_info.node_label, strlen(device->dev_info.node_label));
     }
     else{
         val = esp_matter_char_str("Lockly Smart Lock", strlen("Lockly Smart Lock"));
     }
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::NodeLabel::Id, &val);
 
     ESP_LOGI(TAG, "NodeLabel:%s",device->dev_info.node_label);	
     
     //uint32_t firmwareVersionNumber = getFwVersionNumberFromString(device->dev_info.firmware_version);
     
     //std::string firmwareVersion = device->dev_info.firmware_version;
     // std::replace(firmwareVersion.begin(), firmwareVersion.end(), '.', ' ');
     // ESP_LOGI(TAG, "Firmware Version: %s", firmwareVersion.c_str());
 
     // std::istringstream iss(firmwareVersion);
     // std::string versionPart;
     // uint32_t firmwareVersionNumber = 0;
     // while (std::getline(iss, versionPart, ' ')) {
     // 	uint32_t versionPartNumber = std::stoi(versionPart);
     // 	firmwareVersionNumber = (firmwareVersionNumber << 8) | versionPartNumber;
     // }
     
     //ESP_LOGI(TAG, "Firmware Version Number: %u", (unsigned long)firmwareVersionNumber);
 
     uint32_t hardVersionNumber = 1;
     val = esp_matter_uint32(hardVersionNumber);
     ESP_LOGE(TAG, "+++... Try to add hardware version of the bridgeed device.");
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::HardwareVersion::Id, &val);
 
     val = esp_matter_char_str("1", strlen("1"));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::HardwareVersionString::Id, &val);
     ESP_LOGE(TAG, "HardwareVersionString:%s","1");
 
     uint32_t firmwareVersionNumber = 10306;
     val = esp_matter_uint32(firmwareVersionNumber);
     ESP_LOGI(TAG, "+++... Try to add software version of the bridgeed device.");
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::SoftwareVersion::Id, &val);
     
     val = esp_matter_char_str(device->dev_info.firmware_version, strlen(device->dev_info.firmware_version));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::SoftwareVersionString::Id, &val);
 
     ESP_LOGI(TAG, "SoftwareVersionString:%s",device->dev_info.firmware_version);
     
     DeviceLayer::PlatformMgr().ScheduleWork(SetRequirePINforRemoteOperationAttribute, reinterpret_cast<intptr_t>(device));
     device->dev_info.last_update_time=0;
 }
 
 void InitialiseDoorSensorAttributes(app_bridged_device_t* device)
 {
     cluster_t *cluster = cluster::get(device->dev->endpoint, BooleanState::Id);
     attribute_t *attribute = attribute::get(cluster, BooleanState::Attributes::StateValue::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     if(val.val.b == false)
       device->dev_info.sensor_status = 0x01;
     else 
       device->dev_info.sensor_status = 0x02;
     
     ESP_LOGI(TAG, "InitialiseDoorSensorAttributes, sensor_status:%x,is_online:%x",device->dev_info.sensor_status,device->dev_info.is_online);
     ESP_LOGI(TAG, "InitialiseDoorSensorAttributes, sensor_id:%s",(char *)device->dev_info.sensor_id);
     char VenderName[32]="Lockly";
     val = esp_matter_char_str(VenderName, strlen(VenderName));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::VendorName::Id, &val);
     val = esp_matter_char_str(device->dev_info.sensor_id, strlen(device->dev_info.sensor_id));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::SerialNumber::Id, &val);
     char ProductName[32]="PGA383";
     if(strcmp((char *)device->dev_info.sensor_id, "FFFFFF")==0)
         strcpy(ProductName,"PGAWDS");
     
     val = esp_matter_char_str(ProductName, strlen(ProductName));
     attribute::update(esp_matter::endpoint::get_id(device->dev->endpoint), BridgedDeviceBasicInformation::Id, BridgedDeviceBasicInformation::Attributes::ProductName::Id, &val);
     device->dev_info.last_update_time=0;
 }
 
 void InitialiseHubAttributes(void)
 {
     ESP_LOGI(TAG, "InitialiseHubAttributes");
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     char NodeLabel[32]="LOCKLY MATTER LINK";
     val = esp_matter_char_str(NodeLabel, strlen(NodeLabel));
     attribute::update(0, BasicInformation::Id, BasicInformation::Attributes::NodeLabel::Id, &val);
 }
 
 void SetRequirePINforRemoteOperationAttribute(intptr_t context)
 {
     app_bridged_device_t *device;
     uint16_t endpointId;
     device = (app_bridged_device_t *)context;
     endpointId = esp_matter::endpoint::get_id(device->dev->endpoint);
         
     node_t *node = node::get();
     endpoint_t *endpoint = endpoint::get(node, endpointId);
     cluster_t *cluster = cluster::get(endpoint, DoorLock::Id);
     attribute_t *attribute = attribute::get(cluster, DoorLock::Attributes::RequirePINforRemoteOperation::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     val.val.b = device->dev_info.access_code_enabled;		
     attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::RequirePINforRemoteOperation::Id, &val);
 
     //Set other attributes
     // uint16_t numberOfSupportedUsers = 15;
     // //uint16_t numberOfSupportedCredentials = 0;
     // uint16_t numberOfPINCredentialsSupported  = 15;
     // uint8_t numberOfCredentialsSupportedPerUser = 1;
     // uint8_t numberOfWeekDaySchedulesPerUser = 15;
     // //uint8_t numberOfYearDaySchedulesPerUser = 0;
     // //uint8_t numberOfHolidaySchedules = 0;
     
     // attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfTotalUsersSupported::Id);
     // val = esp_matter_invalid(NULL);
     // attribute::get_val(attribute, &val);
     // val.val.u16 = numberOfSupportedUsers;
     // attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::NumberOfTotalUsersSupported::Id, &val);
     
     // chip::EndpointId aEndpointID;
     // memcpy(&aEndpointID, &endpointId, sizeof(uint16_t));	
     // //DoorLockServer::Instance().SetNumberOfUsersSupported(aEndpointID, numberOfSupportedUsers)
     
     // attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfPINUsersSupported::Id);
     // val = esp_matter_invalid(NULL);
     // attribute::get_val(attribute, &val);
     // val.val.u16 = numberOfPINCredentialsSupported;
     // attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::NumberOfPINUsersSupported::Id, &val);
     // //DoorLockServer::Instance().SetNumberOfPINUsersSupported(aEndpointID, numberOfPINCredentialsSupported)
 
     // //attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfRFIDUsersSupported::Id);
 
     // attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfWeekDaySchedulesSupportedPerUser::Id);
     // val = esp_matter_invalid(NULL);
     // attribute::get_val(attribute, &val);
     // val.val.u16 = numberOfWeekDaySchedulesPerUser;
     // attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::NumberOfWeekDaySchedulesSupportedPerUser::Id, &val);
     // //DoorLockServer::Instance().SetNumberOfWeekDaySchedulesSupportedPerUser(aEndpointID, numberOfWeekDaySchedulesPerUser)
 
     // //attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfYearDaySchedulesSupportedPerUser::Id);
     // attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfCredentialsSupportedPerUser::Id);
     // val = esp_matter_invalid(NULL);
     // attribute::get_val(attribute, &val);
     // val.val.u8 = numberOfCredentialsSupportedPerUser;
     // //attribute = attribute::get(cluster, DoorLock::Attributes::NumberOfHolidaySchedulesSupported::Id);
     // attribute::update(endpointId, DoorLock::Id, DoorLock::Attributes::NumberOfCredentialsSupportedPerUser::Id, &val);
     // //DoorLockServer::Instance().SetNumberOfCredentialsSupportedPerUser(aEndpointID, numberOfCredentialsSupportedPerUser)
     // if(DoorLockServer::Instance().SupportsPIN(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsPIN");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsPIN");
     
     // if(DoorLockServer::Instance().SupportsPIN(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsPIN");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsPIN");
 
     // if(DoorLockServer::Instance().SupportsFingers(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsFingers");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsFingers");
 
     // if(DoorLockServer::Instance().SupportsFace(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsFace");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsFace");
 
     // if(DoorLockServer::Instance().SupportsWeekDaySchedules(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsWeekDaySchedules");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsWeekDaySchedules");
 
     // if(DoorLockServer::Instance().SupportsYearDaySchedules(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsYearDaySchedules");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsYearDaySchedules");
 
     // if(DoorLockServer::Instance().SupportsHolidaySchedules(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsHolidaySchedules");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsHolidaySchedules");
 
     // if(DoorLockServer::Instance().SupportsUSR(aEndpointID))
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, SupportsUSR");
     // else
     // 	ESP_LOGI(TAG, "SetRequirePINforRemoteOperationAttribute, Not SupportsUSR");
 
 }
 
 bool GetRequirePINforRemoteOperationAttribute(app_bridged_device_t* device)
 {
     uint16_t endpointId;
     endpointId = esp_matter::endpoint::get_id(device->dev->endpoint);
         
     node_t *node = node::get();
     endpoint_t *endpoint = endpoint::get(node, endpointId);
     cluster_t *cluster = cluster::get(endpoint, DoorLock::Id);
     attribute_t *attribute = attribute::get(cluster, DoorLock::Attributes::RequirePINforRemoteOperation::Id);
     esp_matter_attr_val_t val = esp_matter_invalid(NULL);
     attribute::get_val(attribute, &val);
     device->dev_info.access_code_enabled = val.val.b;
     return val.val.b;		
 }
 
 
 void WakeupDoorLock(app_bridged_device_t *device)
 {
     if((device)&&(device->dev_info.wakeup_ind)){
         UartSendParm parm;
         parm.handler = NULL;
         unsigned char buffer_temp[9]={0xA1,0xB2,0xC3,0xD4,0x09,0x00,0x01,0x0F,0xF3};	
         uart_sent_ble_data((esp_bd_addr_t *)device->dev_addr.espnow_macaddr, buffer_temp, sizeof(buffer_temp), 5000,6,NULL,parm); 
     }
 }
 